<?php

namespace App\Http\Controllers\Api;

use App\Models\About;
use App\Models\Order;
use App\Models\Pocket;
use App\Services\Api;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Log;
use Symfony\Component\HttpFoundation\Response;
use Yansongda\LaravelPay\Facades\Pay;
use Yansongda\Pay\Contracts\GatewayApplicationInterface;

class PayController extends Controller
{
    public function index(Request $request)
    {
        /**
         * 0. 请求参数
         *  0.1 密码
         *  0.2 订单ID
         *  0.3 支付方式
         *
         * 1. 选择支付方式
         *
         * 2. 调用支付接口
         *
         *  2.1 检查支付密码
         *          => 没有设置支付密码, 则提示去设置支付密码, 状态码: 412
         *          => 支付密码错误, 状态码: 403
         *
         *  2.2 检查订单是否存在 => 订单不存在直接返回, 状态码: 404
         *
         *  2.3 获取订单金额/钱包余额
         *
         *  2.4 比较订单金额与钱包余额
         *      2.4.0 扣款失败 => 状态码: 500, 需要提示重试
         *
         *      2.4.1 钱包余额 >= 订单金额 => 支付成功 => 状态码: 200
         *
         *      2.4.2 钱包余额 < 订单金额 => 根据选择的支付方式返回对应参数
         *          微信/支付宝 => 状态码: 201
         *          线下转账    => 状态码: 202
         *
         *  2.5 返回结果
         *
         * 3. 根据返回, 执行操作
         */
        $data = $request->all([
            'password',
            'order_id',
            'payment',
        ]);

        /** @var Pocket $pocket */
        $pocket = Pocket::where('customer_id', Auth::id())->first();

        if (!$pocket || !$pocket->password) {
            return Api::failure(412, '请先设置支付密码！');
        }

        if (!Hash::check($data['password'], $pocket->password)) {
            return Api::failure(403, '支付密码错误');
        }

        /** @var Order $order */
        if (!$order = Order::where('id', $data['order_id'])->first()) {
            return Api::failure(404, '订单不存在');
        }

        $surplus = $pocket->amount; // 单位: 分

        $money = $order->total_account * 100; // 单位换算成: 分

        $no = $order->order_number;

        if ($money <= $surplus) {// 钱包金额大于等于订单金额, 直接付款成功
            // 钱包支付
            if ($surplus && $pocket->consume($money, 'YS-' . $no) === false) {
                return Api::failure(500, '钱包扣款失败! 请稍后重试...');
            }

            // 添加支付方式
            $order->pay($money, Order::PAYMENT_SELF);

            // 修改状态
            $order->getHint()->pay('钱包支付');

            // 返回
            return Api::success([], '支付完成!');
        } else {
            // 钱包支付
            if ($surplus && $pocket->consume($surplus, 'YS-' . $no) === false) {
                return Api::failure(500, '钱包扣款失败! 请稍后重试...');
            }

            // 添加支付方式
            $order->pay($surplus, Order::PAYMENT_SELF);

            // 剩余应付金额
            $payAmount = $money - $surplus;

            $order->pay($payAmount, $data['payment']);
            return $this->getPayParams($data['payment'], $payAmount, $no);
        }
    }

    /** 临时测试方法 */
    public function web(Request $request)
    {
        $data = $request->all([
            'order_id',
        ]);

        $order = Order::where('id', $data['order_id'])->first();

        return Pay::alipay()->web([
            'out_trade_no' => $order->order_number,
            'total_amount' => price($order->total_account), // 单位: 元
            'subject' => "YS-" . $order->order_number,
        ]);
    }

    protected function getPayParams($payment, $payAmount, $orderNo)
    {
        switch ($payment) {
            case Order::PAYMENT_OFFLINE:
                return $this->offlinePay($payAmount, $orderNo);
                break;
            case Order::PAYMENT_ALIPAY:
                return $this->alipay($payAmount, $orderNo);
                break;
            case Order::PAYMENT_WECHAT:
                return $this->weChatPay($payAmount, $orderNo);
                break;
            default:
                return Api::failure(404, '未知的支付方式');
                break;
        }
    }

    protected function offlinePay($payAmount, $no)
    {
        $data = About::whereType(About::TYPE_OFFLINE)
            ->pluck('meta_value', 'meta_key')->toArray();

        /** @var Order $order */
        $order = Order::where('order_number', $no)->first();

        // 修改状态-选择线下转账-待确认
        $order->getHint()->offlinePayment()->offlinePaid();

        // 7*24 小时后订单自动取消
        $order->update([
            'cancel_at' => now()->addHours(7 * 24)->timestamp
        ]);

        return Api::success([
            'account_name' => $data['account_name'] ?? "",
            'account_no' => $data['account_no'] ?? "",
            'account_bank' => $data['account_bank'] ?? "",
            'account_bank_no' => $data['account_bank_no'] ?? "",
            'money' => price($payAmount / 100),
            'comment' => "YS" . $no,
        ], 'ok', 202);
    }

    protected function aliPay($payAmount, $no)
    {
        $order = [
            'out_trade_no' => $no,
            'total_amount' => price($payAmount / 100), // 单位: 元
            'subject' => "YS-" . $no,
        ];

        return Api::success([
            'code' => Pay::alipay()->app($order)->getContent(),
            'payment' => 'alipay'
        ], 'ok', 201);
    }

    protected function weChatPay($payAmount, $no)
    {
        $order = [
            'out_trade_no' => $no,
            'body' => "YS-" . $no,
            'total_fee' => $payAmount, // 单位: 分
            'openid' => config('pay.wechat.openid'),
        ];

        return Api::success([
            'code' => Pay::wechat()->app($order)->getContent(),
            'payment' => 'alipay'
        ], 'ok', 201);
    }

    /**
     * 支付成功-通知地址
     *
     * @param Request $request
     * @param $payment
     * @return mixed
     */
    public function notify(Request $request, $payment)
    {
        $data = $request->all();

        /** @var GatewayApplicationInterface $pay */
        $pay = Pay::{$payment}();

        try {
            $pay->verify(null, false);

            if ($payment == 'alipay') {
                $this->alipayNotify($data);
            }
        } catch (\Throwable $e) {
            Log::error('签名验证失败', [
                'content' => $request->request->all(),
                'request' => $request->all(),
            ]);
            return Api::failure('500', $e->getMessage());
        }

        return 'success';
    }

    protected function alipayNotify($data)
    {
        if ($data['trade_status'] == 'TRADE_SUCCESS') {

            /** @var Order $order */
            $order = Order::where('order_number', $data['out_trade_no'])->first();

            // 如果支付金额不一致, 直接忽略
            if ($order->payment_money == $data['total_amount'] * 100) {
                // 如果回调返回的时候, 订单自动取消了, 则, 支付的钱直接进入钱包
                if ($order->getHint()->isFinish()) {
                    Log::info('订单已取消, 退款', $data);
                    $order->refund(Order::PAYMENT_ALIPAY);
                } else {
                    Log::info('支付成功', $data);
                    // 流水号
                    $order->update([
                        'payment_no' => $data['trade_no'],
                        'paid_at' => now(),
                    ]);
                    // 修改状态
                    $order->getHint()->pay();
                }
            } else {
                Log::error('回调接口, 支付金额不一致, 忽略', $data);
            }
        } else {
            Log::error('回调接口, 状态不是交易成功, 忽略', $data);
        }
    }
}
